/*
    RC4 Shellcode Encryption using SystemFunction032/033
    By @5mukx
*/

use winapi::{shared::{bcrypt::NTSTATUS, minwindef::UCHAR}, um::libloaderapi::{GetProcAddress, LoadLibraryA}};
use std::ffi::CString;

#[repr(C)]
#[derive(Debug)]
struct UString{
    length: u32,
    maximum_length: u32, 
    buffer: *mut u8,
}

type SystemFunction033 = unsafe extern "system" fn(
    memory_region: *mut UString,
    key_pointer: *mut UString,
) -> NTSTATUS;

pub fn encrypt(shellcode: &mut [u8]){
    unsafe {
        let advapi_word = CString::new("advapi32.dll").expect("error");
        let advapi32 = LoadLibraryA(advapi_word.as_ptr() as *mut i8);
        
        if advapi32.is_null(){
            eprintln!("[-] Failed to load advapi32.dll");
            return;
        }

        println!("[+] Load Address: {:?}", advapi32);

        let system_func_033: SystemFunction033 = {
            
            let systemfunc033 = CString::new("SystemFunction033").expect("Error");
            let func = GetProcAddress(advapi32, systemfunc033.as_ptr() as *mut i8);
            // check
            if func.is_null(){
                eprintln!("[-] Failed to get SystemFunction033 Function");
                return;
            }

            std::mem::transmute(func)
        };

        println!("[+] SystemFunction033 Address: {:?}", system_func_033);
        
        let key_data = CString::new("Smukx_07 :)").expect("erro");
        
        let mut key = UString{
            length: key_data.as_bytes().len() as u32, 
            maximum_length: key_data.as_bytes().len() as u32,
            buffer: key_data.as_ptr() as *mut UCHAR,
        };

        println!("{:?}", key);
        
        let mut data = UString{
            length: shellcode.len() as u32,
            maximum_length: shellcode.len() as u32,
            buffer: shellcode.as_mut_ptr(),
        };

        println!("Shellcode data: {:?}", data);

        let status = system_func_033(&mut data, &mut key);
        if status != 0{
            eprintln!("[-] Encryption Failed with Status: 0x{:?}", status);
            return;
        }

        println!("Encryption Success !");

        print!("let mut shellcode = [");


        for(i, byte) in shellcode.iter().enumerate(){
            if i % 16 == 0{
                println!();
                print!(" ");
            }
            print!("0x{:02X}, ", byte);
        }
        print!("]");
    }
    println!();


}
